﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Microsoft.WowAddonStudio.Project.Import.Folder
{
	/// <summary>
	/// Implements the import of addon items from folder specified by user.
	/// </summary>
	public class FolderImportPlugin : IImportPlugin
	{
		private string rootDirectoryName = string.Empty;

		#region IImportPlugin Members

		/// <summary>
		/// Gets the user interface element used to pick the uri to import from.
		/// </summary>
		/// <returns>An instance of the <see cref="ImportWizardPane"/> class.</returns>
		public ImportWizardPane GetImportWizardPane()
		{
			return new CustomFolderPickerWizardPane();
		}

		/// <summary>
		/// Imports the addon at the given uri.
		/// </summary>
		/// <param name="importSettings">The import settings.</param>
		/// <returns>
		/// An enumerable collection of <see cref="IAddonItem"/>s.
		/// </returns>
		public IEnumerable<IAddonItem> Import(object importSettings)
		{
			if (importSettings == null)
				throw new ArgumentNullException("importSettings");
			if (!(importSettings is FolderImportSettings))
				throw new ArgumentException("Import settigns type mismatch.", "importSettings");

			var folderImportSettings = (FolderImportSettings) importSettings;

			string rootFolderPath = folderImportSettings.SourceUri.LocalPath;
			if (!Directory.Exists(rootFolderPath))
				throw new ArgumentException("Non-existing folder specified for import.");

			var result = new List<IAddonItem>();
			List<string> filePaths = GetAllFilePaths(rootFolderPath);

			foreach (string filePath in filePaths)
			{
				result.Add(CreateAddonItem(rootFolderPath, filePath));

				if (string.IsNullOrEmpty(rootDirectoryName) &&
				    string.Compare(Path.GetExtension(filePath), ".toc", StringComparison.OrdinalIgnoreCase) == 0)
					rootDirectoryName = Path.GetFileNameWithoutExtension(filePath);
			}

			return result;
		}

		/// <summary>
		/// Gets the name of the root directory. Used when the import process
		/// (<see cref="ImportProcess"/>) creates subdirectory under the target
		/// folder based on the value of this property.
		/// </summary>
		/// <value>The name of the root directory.</value>
		public string RootDirectoryName
		{
			get { return rootDirectoryName; }
		}

		#endregion

		#region Private member functions

		/// <summary>
		/// Creates the addon item.
		/// </summary>
		/// <param name="rootFolderPath">The root folder path.</param>
		/// <param name="filePath">The file path.</param>
		/// <returns></returns>
		private static IAddonItem CreateAddonItem(string rootFolderPath, string filePath)
		{
			string relativePath = PathUtils.RelativePathTo(rootFolderPath, filePath);
			return new FolderAddonItem(rootFolderPath, relativePath);
		}

		/// <summary>
		/// Gets all file paths.
		/// </summary>
		/// <param name="rootFolderPath">The root folder path.</param>
		/// <returns></returns>
		private static List<string> GetAllFilePaths(string rootFolderPath)
		{
			var result = new List<string>();

			if (!HiddenDirectory(rootFolderPath))
			{
				result.AddRange(Directory.GetFiles(rootFolderPath)
				                	.Where(file => (new FileInfo(file).Attributes & FileAttributes.Hidden) == 0));

				string[] subFolderEntries = Directory.GetDirectories(rootFolderPath);
				foreach (string subFolder in subFolderEntries)
					result.AddRange(GetAllFilePaths(subFolder));
			}

			return result;
		}

		/// <summary>
		/// Hiddens the directory.
		/// </summary>
		/// <param name="path">The path.</param>
		/// <returns></returns>
		private static bool HiddenDirectory(string path)
		{
			var di = new DirectoryInfo(path);
			return (di.Attributes & FileAttributes.Hidden) != 0;
		}

		#endregion
	}
}